package com.kun.service.service.impl;

import com.kun.dto.PageTable;
import com.kun.dto.ProcessInstanceDto;
import com.kun.service.service.IProcessDefinitionService;
import com.kun.service.service.IProcessInstanceService;
import com.kun.vo.ProcessDefinitionVo;
import com.kun.vo.ProcessInstanceVo;
import lombok.RequiredArgsConstructor;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.model.payloads.DeleteProcessPayload;
import org.activiti.api.process.model.payloads.ResumeProcessPayload;
import org.activiti.api.process.model.payloads.StartProcessPayload;
import org.activiti.api.process.model.payloads.SuspendProcessPayload;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.engine.RuntimeService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ProcessInstanceServiceImpl implements IProcessInstanceService {

    private final ProcessRuntime processRuntime;
    private final RuntimeService runtimeService;
    private final IProcessDefinitionService processDefinitionService;


    /**
     * 分页查询流程定义
     */
    @Override
    public PageTable pageList(ProcessInstanceDto instance) {
        Pageable pageable = Pageable.of(instance.getCurrent() - 1, instance.getPageSize());
        // 仅返回正在进行的或已暂停的流程
        Page<ProcessInstance> processInstancePage = processRuntime.processInstances(pageable);
        // 获取内容
        List<ProcessInstance> content = processInstancePage.getContent();
        // 判断是否为空
        if (content.isEmpty()) return new PageTable(List.of(), 0L);

        // 查询所有流程定义
        Map<String, ProcessDefinitionVo> map = processDefinitionService.selectList().
                stream().collect(Collectors.toMap(ProcessDefinitionVo::getKey, Function.identity()));

        // 查询流程定义
        List<ProcessInstanceVo> list = content.stream().map(processInstance -> {
            ProcessDefinitionVo processDefinitionVo = map.get(processInstance.getProcessDefinitionKey());
            return new ProcessInstanceVo(processInstance.getId(), processInstance.getName(),
                    processInstance.getStartDate(), processInstance.getStatus(), processDefinitionVo.getDeploymentId(),
                    processInstance.getProcessDefinitionKey(), processInstance.getProcessDefinitionVersion(),
                    processDefinitionVo.getResourceName());
        }).toList();
        // 获取总数
        long totalItems = processInstancePage.getTotalItems();
        return new PageTable(list, totalItems);
    }

    /**
     * 修改流程实例状态
     */
    @Override
    public boolean updateStatus(String id) {
        ProcessInstance processInstance = processRuntime.processInstance(id);
        Assert.isTrue(processInstance != null, "流程实例不存在");
        // 根据Id查询出来流程实例
        if (processInstance.getStatus().equals(ProcessInstance.ProcessInstanceStatus.RUNNING)) {
            // 挂起
            SuspendProcessPayload build = ProcessPayloadBuilder.suspend().withProcessInstanceId(id).build();
            processRuntime.suspend(build);
        } else if (processInstance.getStatus().equals(ProcessInstance.ProcessInstanceStatus.SUSPENDED)) {
            // 激活
            ResumeProcessPayload build = ProcessPayloadBuilder.resume().withProcessInstanceId(id).build();
            processRuntime.resume(build);
        }
        return true;
    }

    /**
     * 启动流程实例
     */
    @Override
    public boolean startInstance(String processDefinitionKey, String name) {
        // 启动流程实例
        StartProcessPayload build = ProcessPayloadBuilder.start()
                // 流程key
                .withProcessDefinitionKey(processDefinitionKey)
                // 启动名称
                .withName(name)
//                .withVariable("key", "value") // 不需要可以去除
//                .withBusinessKey("自定义的参数‘") // 不需要可以去除
                .build();
        processRuntime.start(build);
        return true;
    }

    /**
     * 删除流程实例
     */
    @Override
    public boolean deleteById(String instanceId) {
        // 删除流程实例
        DeleteProcessPayload build = ProcessPayloadBuilder.delete().withProcessInstanceId(instanceId).build();
        processRuntime.delete(build);
        return true;
    }

    /**
     * 在集合中根据ID查询指定流程实例
     */
    @Override
    public org.activiti.engine.runtime.ProcessInstance findProcessInstanceById(List<org.activiti.engine.runtime.ProcessInstance>
                                                                                       processInstanceVoList, String processInstanceId) {
        return processInstanceVoList.stream().filter(processInstanceVo ->
                processInstanceVo.getId().equals(processInstanceId)).findFirst().orElse(null);
    }

    /**
     * 获取所有的流程实例
     */
    @Override
    public List<org.activiti.engine.runtime.ProcessInstance> getInstanceList() {
        return runtimeService.createProcessInstanceQuery().list();
    }
}
